/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include <向量.h>
#include <材质/材质.h>
#include <场景/场景.h>
#include <场景/intern/S_Scene.h>

#include "材质纹理JIT函数绑定.h"
#include "Context/当前默认操作数据.h"

#include <core/shader_noise.h>
#include <core/shader_texture.h>
#include <底层绘图/底层绘图框架.h>
#include <底层绘图/S_纹理.h>







void f_JIT_简单噪波生成(uint32 num, vec3* offset, vec3* scale, float32* 强度, bool 单例[3], S_F32Array* 噪波, float32 n) {
	if (!num) return;

	f_core_array_resize((S_Array*)噪波, num);

	float32* 噪波_ptr = 噪波->ptr_userData;

	for (uint32 i = 0; i < num; ++i) {
		vec3 c{};

		
		if (单例[0]) c += offset[0];
		else c += offset[i];
		//c += n;

		if (单例[1]) c *= scale[0];
		else c *= scale[i];


		float32 a;
		if (单例[2]) a = 强度[0];
		else a = 强度[i];

		噪波_ptr[i] = a * f_glsl_simplexNoise(_Vec2(c));
	}
}

void f_JIT_2D噪波生成(uint32 num, vec2* offset, vec2* scale, float32* 强度, bool 单例[3], S_Vec2Array* 噪波) {
	if (!num) return;

	f_core_array_resize((S_Array*)噪波, num);

	vec2* 噪波_ptr = 噪波->ptr_userData;

	for (uint32 i = 0; i < num; ++i) {
		vec2 c;
		if (单例[0]) c = offset[0];
		else c = offset[i];

		if (单例[1]) c += scale[0];
		else c += scale[i];

		float32 a;
		if (单例[2]) a = 强度[0];
		else a = 强度[i];

		vec3 noise = f_perlin2DNoise(c, true);
		噪波_ptr[i].x = noise.x * a;
		噪波_ptr[i].y = noise.y * a;
	}
}

void f_JIT_3D噪波生成(uint32 num, vec3* offset, vec3* scale, float32* 强度, bool 单例[3], S_Vec3Array* 噪波) {
	if (!num) return;

	f_core_array_resize((S_Array*)噪波, num);

	vec3* 噪波_ptr = 噪波->ptr_userData;

	for (uint32 i = 0; i < num; ++i) {
		vec3 c;
		if (单例[0]) c = offset[0];
		else c = offset[i];

		if (单例[1]) c += scale[0];
		else c += scale[i];

		float32 a;
		if (单例[2]) a = 强度[0];
		else a = 强度[i];

		vec3 noise = f_perlin2DNoise({c.x, c.y}, true);
		噪波_ptr[i] = noise * a;
	}
}

S_材质管线* export_create_material(uint32 设备ID) {
	S_材质管线* 材质 = f_material_createPBR();

	return 材质;
}

int32 f_JIT_getGPU纹理ID(S_纹理* 纹理) {
	return 纹理->m_TexID;
}

int32 f_JIT_get字符纹理坐标(S_字体& 字体, S_Props& 文本, S_Vec3Array* 坐标, S_Vec2Array* 大小, int32* 坐标类型) {
	auto& str = f_prop_Str(文本);

	uint32 num = str.size();
	f_core_array_resize((S_Array*)坐标, num);
	f_core_array_resize((S_Array*)大小, num);

	vec3 size = {1,1};
	if (字体.m_Tex) {
		size = { float32(字体.m_Tex->m_Size.x), float32(字体.m_Tex->m_Size.y), 1 };
	}
	switch (*坐标类型) {
		case 0: {
			for (uint32 i = 0; i < num; ++i) {
				auto& r = 字体.m_uv偏移[str[i]];
				坐标->ptr_userData[i] = r / size;
				//大小->ptr_userData[i] = vec2{ 字体.m_字符大小[str[i]].x, float32(字体.m_字号) } / vec2{ size.x, size.y };
				大小->ptr_userData[i] = 字体.m_字符大小[str[i]] / vec2{size.x, size.y};
			}
			break;
		}
		case 1: {
			for (uint32 i = 0; i < num; ++i) {
				auto& r = 字体.m_uv偏移[str[i]];
				坐标->ptr_userData[i] = r;
				大小->ptr_userData[i] = 字体.m_字符大小[str[i]];
			}
			break;
		}
	}
	return num;
}

void f_JIT_get字符纹理排列(S_字体& 字体, 
	S_Props& 文本, 
	S_Vec2Array* 坐标, 
	S_Vec2Array* 大小, 
	int32* 方向, 
	float32 缩放, 
	float32 间隔, 
	float32 上下偏移) {
	auto& str = f_prop_Str(文本);

	uint32 num = str.size();
	f_core_array_resize((S_Array*)坐标, num);
	f_core_array_resize((S_Array*)大小, num);

	switch (*方向) {
		case 0: {
			float32 推进 = 0;
			for (uint32 i = 0; i < num; ++i) {
				auto& t = str[i];
				auto& r = 字体.m_uv偏移[t];

				坐标->ptr_userData[i] = vec2{ 推进 - 字体.m_区域[t].左边, -字体.m_区域[t].顶边 * 上下偏移 } * 缩放;
				大小->ptr_userData[i] = 字体.m_字符大小[t] * 缩放;

				推进 += 大小->ptr_userData[i].x + 间隔;
			}
			break;
		}
		case 1: {
			break;
		}
	}

}


void f_JIT_清除材质自定义网格数据布局参数(S_材质管线& 材质) {
	材质.m_网格自定义属性布局.clear();

	for (auto& e : 材质.m_自定义属性) {
		f_bm_erase(e);
	}
	材质.m_自定义属性.clear();

	for (uint32 i = 0; i < 16; ++i) {
		f_buf_属性索引_at(材质.m_材质自定义属性索引, i) = {};
	}
}

void f_JIT_添加材质自定义网格数据布局参数(S_材质管线& 材质, const S_网格自定义属性* 属性) {
	//switch (属性->m_Type) {
	//	default:
	//		break;
	//}
	材质.m_网格自定义属性布局.push_back(*属性);
	//材质.m_自定义属性布局.back().m_OffsetID = 材质.m_自定义属性布局.size() - 1;
}

void f_JIT_设置材质字体纹理自定义属性偏移(S_材质管线& mat, uint32 offset, S_字体& f) {
	if (f.m_Tex) {
		f_buf_属性索引_at(mat.m_材质自定义属性索引, offset).offset = f.m_Tex->m_TexID;
	}
}

void f_JIT_设置材质纹理自定义属性偏移(S_材质管线& mat, uint32 offset, S_纹理* tex) {
	if (tex) {
		f_buf_属性索引_at(mat.m_材质自定义属性索引, offset).offset = tex->m_TexID;
	}
	else {
		f_buf_属性索引_at(mat.m_材质自定义属性索引, offset).offset = 0;
	}
}

void f_JIT_添加材质着色器自定义参数(S_材质管线& 材质, E_值类型 类型, uint32 offset) {
	S_GPU内存块 块{};
	switch (类型) {
		case E_值类型::e_Type_F32: 块 = f_bm_alloc(f_buf_getGlobal().m_F32动态属性, 1); break;

		case E_值类型::e_Type_I32: 块 = f_bm_alloc(f_buf_getGlobal().m_I32动态属性, 1); break;

		case E_值类型::e_Type_UI32: 块 = f_bm_alloc(f_buf_getGlobal().m_UI32动态属性, 1); break;

		case E_值类型::e_Type_Vec2: 块 = f_bm_alloc(f_buf_getGlobal().m_Vec2动态属性, 1); break;

		case E_值类型::e_Type_Vec3: 块 = f_bm_alloc(f_buf_getGlobal().m_Vec3动态属性, 1); break;

		case E_值类型::e_Type_Vec4: 块 = f_bm_alloc(f_buf_getGlobal().m_Vec4动态属性, 1); break;
	}

	f_buf_属性索引_at(材质.m_材质自定义属性索引, offset) = { 块.m_Mem.m_偏移, 1 };
	材质.m_自定义属性.push_back(块);
}

void f_JIT_设置材质自定义属性值(S_材质管线& 材质, E_值类型 类型, uint32 offset, void* val) {
	switch (类型) {
		case E_值类型::e_Type_F32: f_buf_F32_at(材质.m_自定义属性[offset]) = (*(float32*)val); break;

		case E_值类型::e_Type_I32: f_buf_I32_at(材质.m_自定义属性[offset]) = (*(int32*)val); break;

		case E_值类型::e_Type_UI32: f_buf_UI32_at(材质.m_自定义属性[offset]) = (*(uint32*)val); break;

		case E_值类型::e_Type_Vec2: f_buf_Vec2_at(材质.m_自定义属性[offset]) = (*(vec2*)val); break;

		case E_值类型::e_Type_Vec3: f_buf_Vec3_at(材质.m_自定义属性[offset]) = (*(vec3*)val); break;

		case E_值类型::e_Type_Vec4: f_buf_Vec4_at(材质.m_自定义属性[offset]) = (*(vec4*)val); break;
	}
}




void f_JIT_get纹理属性(S_纹理* 纹理, uvec2& 分辨率, uint32& 通道, uint32& 位宽) {
	分辨率 = { 纹理->m_Size.x, 纹理->m_Size.y };
	位宽 = 8;
	通道 = 4;
}

void f_JIT_执行毛笔笔刷(S_Brush_Maobi* 笔刷属性) {
	
}


static void f_JIT_upGPU计算参数(S_GPU计算* device, const S_GPU参数槽* GPU参数) {
	S_GlobalParam 全局参数 = f_df_全局GPU参数();
	*f_buf_全局GPU参数指针_ptr(f_buf_getGlobal().g_全局绑定参数) = 全局参数;


	GPU参数->m_参数槽[0] = f_scene_get纹理集(f_NodeCtx_get默认场景());
	GPU参数->m_参数类型[0] = E_板载缓存类型::e_IMAGE_Array;
	GPU参数->m_绑定位置[0] = DEF_TexturesBindID;
	GPU参数->m_绑定数量[0] = f_scene_get纹理集数量(f_NodeCtx_get默认场景());

	GPU参数->m_参数槽[1] = &f_buf_getGlobal().g_全局绑定参数;
	GPU参数->m_参数类型[1] = E_板载缓存类型::e_SSBO;
	GPU参数->m_绑定位置[1] = DEF_BINDING_Render_GlobalParam;
	GPU参数->m_绑定数量[1] = 1;

	f_df_upGPU参数(device->m_Ctx.m_逻辑设备.设备, device->m_GPU参数set, *GPU参数);
}

static void f_JIT_upGPU纹理笔刷参数(S_GPU计算* device, const S_GPU参数槽* GPU参数) {
	S_GlobalParam 全局参数 = f_df_全局GPU参数();
	*f_buf_全局GPU参数指针_ptr(f_buf_getGlobal().g_全局绑定参数) = 全局参数;

	GPU参数->m_参数槽[0] = &f_buf_getGlobal().g_全局绑定参数;
	GPU参数->m_参数类型[0] = E_板载缓存类型::e_SSBO;
	GPU参数->m_绑定位置[0] = DEF_BINDING_Render_GlobalParam;
	GPU参数->m_绑定数量[0] = 1;

	GPU参数->m_参数槽[1] = f_scene_get纹理集(f_NodeCtx_get默认场景());
	GPU参数->m_参数类型[1] = E_板载缓存类型::e_IMAGE_Array;
	GPU参数->m_绑定位置[1] = DEF_TexturesBindID;
	GPU参数->m_绑定数量[1] = f_scene_get纹理集数量(f_NodeCtx_get默认场景());

	//S_全局缓存::g_全局模型纹理槽.m_纹理参数[0] = f_scene_get纹理集(f_NodeCtx_get默认场景());
	//S_全局缓存::g_全局模型纹理槽.m_绑定数量[0] = f_scene_get纹理集数量(f_NodeCtx_get默认场景());
	//S_全局缓存::g_全局模型纹理槽.m_绑定位置[0] = DEF_TasterTexturesBindID_rgba8;

	f_df_upGPU参数(device->m_Ctx.m_逻辑设备.设备, device->m_GPU参数set, *GPU参数);
}


void f_JIT_绑定材质着色器(S_材质管线& 材质, const S_材质管线& 着色器母材质) {
	材质.m_着色线管 = 着色器母材质.m_着色线管;
	材质.mf_GPU参数配置 = 着色器母材质.mf_GPU参数配置;
	材质.m_引用着色线管 = true;
}

void f_JIT_解绑材质着色器(S_材质管线& 材质) {
	材质.m_着色线管->m_Shader = nullptr;
	材质.m_着色线管->m_Pipeline = nullptr;
	材质.m_着色线管->m_GPU参数set = nullptr;
	材质.mf_GPU参数配置 = nullptr;
	材质.m_引用着色线管 = false;
}


void f_node_所有材质纹理节点JIT初始化() {
	f_代码构建_添加JIT初始化函数指针(DEF_S(f_glsl_simplexNoise), "float32", "vec2 uv", f_glsl_simplexNoise);
	f_代码构建_添加JIT初始化函数指针(DEF_S(f_perlin2DNoise), "vec3", "vec2 uv, bool revert", f_perlin2DNoise);
	f_代码构建_添加JIT初始化函数指针(DEF_S(f_texture_Gradient), "vec3", "vec3 uv, int type", f_texture_Gradient);

	f_代码构建_添加JIT初始化函数指针(DEF_S(f_JIT_简单噪波生成), "void", "uint32 num, vec3* offset, vec3* scale, float32* 强度, bool 单例[3], S_F32Array* 噪波, float32 n", f_JIT_简单噪波生成);


	f_代码构建_添加JIT初始化函数指针(DEF_S(f_JIT_getGPU纹理ID), DEF_S(int32), "S_纹理*", f_JIT_getGPU纹理ID);
	f_代码构建_添加JIT初始化函数指针(DEF_S(f_JIT_get字符纹理坐标), DEF_S(int32), "S_字体& , S_Props& , S_Vec3Array*, S_Vec2Array* , int32*", f_JIT_get字符纹理坐标);
	f_代码构建_添加JIT初始化函数指针(DEF_S(f_JIT_get字符纹理排列), DEF_S(int32), "S_字体& , S_Props& , S_Vec2Array*, S_Vec2Array* , int32*, float32, float32, float32", f_JIT_get字符纹理排列);

	f_代码构建_添加JIT初始化函数指针(DEF_S(f_JIT_清除材质自定义网格数据布局参数), DEF_S(void), "S_材质& ", f_JIT_清除材质自定义网格数据布局参数);
	f_代码构建_添加JIT初始化函数指针(DEF_S(f_JIT_添加材质自定义网格数据布局参数), DEF_S(void), "S_材质管线& , const S_网格自定义属性* ", f_JIT_添加材质自定义网格数据布局参数);
	f_代码构建_添加JIT初始化函数指针(DEF_S(f_JIT_添加材质着色器自定义参数), DEF_S(void), "S_材质管线& 材质, E_值类型 类型, uint32 offset", f_JIT_添加材质着色器自定义参数);

	f_代码构建_添加JIT初始化函数指针(DEF_S(f_JIT_设置材质字体纹理自定义属性偏移), DEF_S(void), "S_材质管线& , uint32 , S_字体& ", f_JIT_设置材质字体纹理自定义属性偏移);
	f_代码构建_添加JIT初始化函数指针(DEF_S(f_JIT_设置材质纹理自定义属性偏移), DEF_S(void), "S_材质管线& , uint32 , S_纹理* ", f_JIT_设置材质纹理自定义属性偏移);
	f_代码构建_添加JIT初始化函数指针(DEF_S(f_JIT_设置材质自定义属性值), DEF_S(void), "S_材质管线& 材质, E_值类型 类型, uint32 offset, void* val", f_JIT_设置材质自定义属性值);

	f_代码构建_添加JIT初始化函数指针(DEF_S(f_tex_从文件加载纹理), DEF_S(void), "S_纹理* tex, const S_Props& , int32 ", f_tex_从文件加载纹理);
	f_代码构建_添加JIT初始化函数指针(DEF_S(f_tex_纹理保存到文件), DEF_S(void), "S_纹理* , const S_Props& , const S_Props&, const S_Props& ", f_tex_纹理保存到文件);
	f_代码构建_添加JIT初始化函数指针(DEF_S(f_tex_重置2D纹理大小), DEF_S(void), "S_纹理* , S_纹理* , uvec2 ", f_tex_重置2D纹理大小);
	f_代码构建_添加JIT初始化函数指针(DEF_S(f_tex_分辨率), DEF_S(uvec3), "S_纹理* ", f_tex_分辨率);
	f_代码构建_添加JIT初始化函数指针(DEF_S(f_JIT_get纹理属性), DEF_S(void), "S_纹理* , uvec2& , uint32& , uint32& ", f_JIT_get纹理属性);

	f_代码构建_添加JIT初始化函数指针(DEF_S(f_tex_创建图像纹理), DEF_S(S_纹理*), "S_设备环境& , const uvec3& , E_纹理格式 , E_纹理维度类型 , E_MS次数 采样, E_纹理排列  ", f_tex_创建图像纹理);
	//f_代码构建_添加JIT初始化函数指针(DEF_S(f_tex_创建图像), DEF_S(S_纹理*), "S_设备环境& , const uvec3& , E_纹理格式 , E_纹理维度类型 ", f_tex_创建图像);
	f_代码构建_添加JIT初始化函数指针(DEF_S(f_tex_销毁纹理), DEF_S(void), "S_纹理* ", f_tex_销毁纹理);


	f_代码构建_添加JIT初始化函数指针(DEF_S(f_JIT_重新加载纹理), DEF_S(void), "void* , int32 ", f_JIT_重新加载纹理);
	f_代码构建_添加JIT初始化函数指针(DEF_S(f_JIT_绑定材质着色器), DEF_S(void), "S_材质管线& 材质, const S_材质& 着色器母材质", f_JIT_绑定材质着色器);

	f_代码构建_添加JIT初始化函数指针(DEF_S(f_GPU_run计算), DEF_S(void), "S_GPU计算* gpu, uvec3 dim, void* data, uint32 size, uint8 列队", f_GPU_run计算);
	f_代码构建_添加JIT初始化函数指针(DEF_S(f_JIT_upGPU纹理笔刷参数), DEF_S(void), "S_GPU计算* gpu, const S_GPU参数槽* GPU参数", f_JIT_upGPU纹理笔刷参数);
	f_代码构建_添加JIT初始化函数指针(DEF_S(f_JIT_upGPU计算参数), DEF_S(void), "S_GPU计算* gpu, const S_GPU参数槽* GPU参数", f_JIT_upGPU计算参数);




}


void f_node_材质纹理计数环境创建(S_设备环境& 绘图环境) {
	auto SPV文件路径 = S_引擎配置::m_3D着色器文件根路径 + "毛笔笔刷.spv";

	std::vector<S_常量推送创建参数> 毛笔笔刷_常量 = {
				{E_着色阶段::e_计算着色, 0, sizeof(S_Brush_Maobi)},
	};
	std::vector<S_着色器创建参数> 毛笔笔刷_参数配置 = {
		{DEF_BINDING_Render_GlobalParam, E_着色阶段::e_计算着色, E_板载缓存类型::e_SSBO},
		{DEF_TexturesBindID, E_着色阶段::e_计算着色, E_板载缓存类型::e_IMAGE_Array},
	};
	//S_节点数据::g毛笔笔刷_计算环境 = f_df_创建并行计算(绘图环境, SPV文件路径, 毛笔笔刷_参数配置, 毛笔笔刷_常量);

	auto SPV单色笔刷文件路径 = S_引擎配置::m_3D着色器文件根路径 + "单色笔刷.spv";

	std::vector<S_常量推送创建参数> 单色笔刷_常量 = {
				{E_着色阶段::e_计算着色, 0, sizeof(S_Brush_Monochrome)},
	};
	//S_节点数据::g单色纹理笔刷_计算环境 = f_df_创建并行计算(绘图环境, SPV单色笔刷文件路径, 毛笔笔刷_参数配置, 单色笔刷_常量);

}

void f_node_材质纹理计数环境销毁() {
	f_df_销毁并行计算(S_节点数据::g毛笔笔刷_计算环境);
	f_df_销毁并行计算(S_节点数据::g单色纹理笔刷_计算环境);
}


